package com.AdvancedDemos.Learn特殊文件;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;

public class LearnXML {
    public static void main(String[] args) throws DocumentException {
        /**
         * XML（全称EXtensible Markup Language，可扩展标记语言)
         *
         * 本质是一种数据的格式，可以用来存储复杂的数据结构，和数据关系。
         *
         * XML的特点
         * XML中的“<标签名>”称为一个标签或一个元素，一般是成对出现的
         * XML中的标签名可以自己定义（可扩展），标签用中文都可以,但必须要正确的嵌套
         * XML中只能有一个根标签
         * XML中的标签可以有属性,键值对的形式
         * 如果一个文件中放置的是XML格式的数据，这个文件就是XML文件，后缀一般要写成.xml
         *
         * 应用场景:经常用来做为系统的配置文件;或者作为一种特殊的数据结构，在网络中进行传输。
         */


        //注意:程序员并不需要自己写原始的IO流代码来解析XML，难度较大!也相当繁琐!
        //其实，有很多开源的，好用的，解析XML的框架，最知名的是:Dom4j(第三方研发的),Document For Java 针对Java提供的解析xml文件的工具


        //使用Dom4j.jar解析XML文件,获取内容
        //①下载Dom4j框架，官网下载。
        //②在模块/项目下创建一个文件夹:lib
        //③将dom4j-2.1.3.jar文件复制到lib文件夹
        //④在jar文件上点右键，选择Add as Library ->点击OK
        //⑤在类中导包使用


        //解析操作
        // 1.使用SAXReader(Simple API for XML Reader)解析器类读取xml文件整体得到Document类对象代表整个文档
        // 2.Document可以获取Element类型根标签,子标签
        // 3.Element可以继续获取 标签属性 和 标签文本内容


        /**
         * SAXReader类(Simple API for XML Reader)(Dom4j提供的解析器，可以认为是代表整个Dom4j框架):
         * public SAXReader() --- 构建Dom4J的解析器对象
         * public Document read(String url) --- 把XML文件读成Document对象
         * public Document read(InputStream is) --- 通过字节输入流读取XML文件
         *
         * Document类:
         * Element getRootElement() --- 获得根元素对象
         */

        //解析操作步骤:
        //1.创建SAXReader解析器对象
        SAXReader saxReader = new SAXReader();
        //2.通过.xml文件路径，读取文件整体
        Document document = saxReader.read("helloworld/src/com/AdvancedDemos/Learn特殊文件/stu_info.xml");//双反斜杠"\\"会报错
        //3.从文档对象中解析全部XML数据
        Element rootElement = document.getRootElement();//拿到根元素对象
        System.out.println("根元素名称为:" + rootElement.getName());//根元素名称为:students

        /**
         Element类:
         public String getName() --- 得到元素名字
         public List<Element> elements() --- 得到当前元素下所有子元素
         public List<Element> elements(String name) --- 得到当前元素下指定名字的子元素返回集合
         public Element element(String name) --- 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
         public String attributeValue(String name) --- 通过属性名直接得到属性值
         Attribute attribute(String var1) --- 拿到指定的属性对象,再getName() getValue()
         public String elementText(子元素名) --- 得到指定名称的子元素的文本
         public String elementTextTrim(String var1) --- 得到指定名称的子元素的文本,并去除两侧的空格
         public String getText() --- 得到元素的文本
         public String getTextTrim() --- 得到元素的文本,并去除两侧的空格
         */

        //4.获取根元素下的全部一级子元素
        System.out.println("--------------");
        List<Element> elements = rootElement.elements();
        for (Element element : elements) {//获取每一个student
            System.out.println(element.getName());
            //student
            //people
            //people
            //student
        }
        System.out.println("--------------");
        elements = rootElement.elements("student");
        Iterator<Element> iterator = elements.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().getName());
            //student
            //studen
        }

        //5.获取当前元素下的某个子元素
        System.out.println("--------------");
        Element people = rootElement.element("people");
        System.out.println(people.getText());//这是1个人
        System.out.println("--------------");
        //得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
        Element student = rootElement.element("student");
        System.out.println(student.elementText("name")/*得到指定名称的子元素的文本*/);//张无忌


        //6.获取元素的属性信息
        System.out.println("--------------");
        System.out.println(student.attributeValue("id"));//1
        Attribute id = student.attribute("id");//或者可以获取Attribute对象,再调其getName getValue方法
        System.out.println(id.getName());//id
        System.out.println(id.getValue());//1
        Attribute desc = student.attribute("desc");
        System.out.println(desc.getName());//desc
        System.out.println(desc.getValue());//第一个学生

        System.out.println("--------------");
        //一次性获取元素的所有属性
        List<Attribute> attributes = student.attributes();
        attributes.forEach(new Consumer<Attribute>() {
            @Override
            public void accept(Attribute attribute) {
                System.out.println(attribute.getName() + "=" + attribute.getValue());
                //id=1
                //desc=第一个学生
            }
        });


        //7.获取元素文本内容
        System.out.println("--------------");
        String name = student.elementText("name");//获取当前元素下的子元素文本值
        System.out.println("name:" + name);//name:张无忌
        String 地址 = student.elementTextTrim("地址");//去空格
        System.out.println("地址:" + 地址);//地址:光明顶
        String password = student.elementText("password");
        System.out.println("password:" + password);//password:minmin
        System.out.println("data:" + student.elementText("data"));//data:3 < 2 && 5 > 4
        System.out.println("--------------");
        Element gender = student.element("gender");//先拿到子元素
        System.out.println(gender.getText());//再直接获取子元素自己的文本//男
        System.out.println(student.element("data").getText());//3 < 2 && 5 > 4
        System.out.println(student.element("testTrim").getTextTrim()/*去空格*/);//a b c


//---------------------------------------------------

        /**
         * 如何使用程序把数据写出到XML文件中去?
         * 不建议使用Dom4j做
         * 推荐直接把程序里的数据拼接成XML格式,然后用IO流写出去
         */
        System.out.println("---------------");
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        stringBuilder.append("<book>\r\n");
        stringBuilder.append("\t<name>").append("从入门到跑路").append("</name>\r\n");
        stringBuilder.append("\t<author>").append("dilei").append("</author>\r\n");
        stringBuilder.append("</book>\r\n");
        System.out.println(stringBuilder);
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("helloworld\\src\\com\\AdvancedDemos\\Learn特殊文件\\myXML.xml"))) {
            bw.write(stringBuilder.toString());
            System.out.println("写出成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}